

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;

/**
 * The Grids class creates all of the remaining 'table-like' structures for the hostess and manager,
 * regardless of the number of rows and columns.  A scrolling function has been added when more than
 * 8 rows are available.  Additional code needs to be written to modify any text written into
 * the text areas.  Additional testing needs to be done to determine how this looks within multiple
 * panes rather than a stand-alone screen. 
 * @author Mike Jones
 * @version 1.0
 */
public class Grids extends JPanel {

	private static JPanel mainPanel;
	private static JPanel rowPanel;
	private static JPanel headerPanel;
	private static JLabel label;
	private static JScrollPane scroll;
	private  JTextArea ha;
	private  static JTextArea ta;
	private static boolean highlight; //used to control only having one row selected at a time
	private static int rowIndex;
	private static char sort = 'D';

	//Holds just the header row (made up of JTextAreas) 
	private static ArrayList<JTextArea> headerArray;

	//Holds just one row of JTextAreas (not including header)
	private static ArrayList<JTextArea> rowArray;

	//This is an arraylist of an arraylist of JTextAreas (2D ArrayList)
	//Not including header row
	private static  ArrayList<ArrayList<JTextArea>> dataArray;

	private static  Toolkit tk = Toolkit.getDefaultToolkit();


	/**
	 * Holds the values for the maximum height and width for the user screen size.
	 */
	private static int screenWidth = (int) tk.getScreenSize().getWidth();
	private static int screenHeight = ((int) (tk.getScreenSize().getHeight()));


	/**
	 * Creates two arrays of JTextAreas, one for the headers and the other for 
	 * everything else.  Text can be changed by cycling through the ArrayLists.
	 * @param headerNum - the number of header columns
	 * @param headerName - an arraylist of strings for the header names
	 * @param total - the number of total rows (DO NOT INCLUDE HEADER IN COUNT)
	 * @param rowData - the arraylist of strings of the database data
	 */
	public Grids (int headerNum, ArrayList<String> headerName, int total, ArrayList<String> rowData){
		//set up to ensure the grid displays a minimum of 7 rows, including the header, at all times
		if(total < 6){
			int end = (((6-total)*headerNum)+rowData.size());
			for(int i = rowData.size(); i <= end; i++){
				rowData.add("");
			}
			total=6;
		}
		setLayout(new BorderLayout());
		mainPanel = new JPanel();
		mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
		makeLabels(headerNum, headerName);
		mainPanel.add(headerPanel);
		dataArray = new ArrayList<ArrayList<JTextArea>>();
		int arrayNum = 0;
		int totalCount = total*headerNum;
		for(int i = 0; i < total; i++){
			makeGrid(headerNum, rowData, i, arrayNum);
			if (totalCount-headerNum >= headerNum){
				arrayNum = arrayNum+headerNum;
			}
			else {
				arrayNum = arrayNum + (totalCount-headerNum);
			}
			totalCount=totalCount-headerNum;
			mainPanel.add(rowPanel);
		}

		//Default to display on a screen without a scroll bar is 7 (8 including header)
		if (total > 7) {
			scroll = new JScrollPane(mainPanel);
			scroll.setVerticalScrollBarPolicy(scroll.VERTICAL_SCROLLBAR_ALWAYS);
			scroll.getVerticalScrollBar().setPreferredSize(new Dimension(screenWidth/25, 0));
			this.add(scroll, BorderLayout.CENTER);
		}
		else{
			this.add(mainPanel);
		}
		//System.out.println(dataArray.get(1).get(2).getText());
	}//End of Constructor

	/**
	 * Makes the header row with corresponding labels
	 * @param num - the number of columns
	 * @param name - the arraylist of header titles
	 */
	private void makeLabels(int num, ArrayList<String> name){

		headerPanel = new JPanel();
		headerPanel.setLayout(new GridLayout(1,num));
		headerPanel.setBorder(BorderFactory.createLineBorder(Color.white, 2));
		headerPanel.setPreferredSize(new Dimension(screenWidth/8, screenHeight/8));
		headerArray = new ArrayList<JTextArea>();


		for (String s : name){
			ha = new JTextArea();
			ha.setEditable(false);
			ha.setLineWrap(true);
			ha.setWrapStyleWord(true);
			ha.setBackground(new Color(91,155,213));
			ha.setForeground(Color.white);
			ha.setText(s);
			ha.setBorder(BorderFactory.createLineBorder(Color.white, 2));
			ha.setPreferredSize(ha.getPreferredSize());
			ha.setFont(new Font("Arial", Font.PLAIN, 25));
			ha.addMouseListener(new MouseListener(){

				public void mouseClicked(MouseEvent e) {
					JTextArea temp = (JTextArea) e.getSource();
					for(int i = 0; i < headerArray.size(); i++){
						if(temp.getText().equals(headerArray.get(i).getText())){
							//if sort is to be displayed ASCENDING
							if(sort == 'D'){
								String sorter = headerArray.get(i).getText();//The column name to be sorted by
								sort = 'A';
								System.out.println(sort);
								//Some Database call here passing in sorter for ASCENDING sort
								//addNewResult(null, headerArray);
								//uncomment the previous method and replace the null value with the ordered 
								//ArrayList<String> given by the database
							}
							else{//if the sort is to be displayed DESCENDING
								String sorter = headerArray.get(i).getText();//The column name to be sorted by
								sort = 'D';
								System.out.println(sort);
								//Some Database call here passing in sorter for DESCENDING
								//addNewResult(null, headerArray);
								//uncomment the previous method and replace the null value with the ordered 
								//ArrayList<String> given by the database
							}
							break;
						}
					}

				}

				public void mouseEntered(MouseEvent e) {
					
				}

				public void mouseExited(MouseEvent e) {
					
				}

				public void mousePressed(MouseEvent e) {
				
				}

				public void mouseReleased(MouseEvent e) {
					
				}
				
			});//End mouselistener for column headers

			headerPanel.add(ha);
			headerArray.add(ha);
		}

	}//End of makeLabels method

	/**
	 * Makes the remaining rows underneath the header
	 * @param hnum - the number of columns
	 * @param rowData - an arraylist of text for the JTextField
	 * @param row - the row number
	 * @param arrayNum - the incrementer for where to start in rowData (increments by number of columns)
	 */
	private static void makeGrid(int hnum, ArrayList<String> rowData, int row, int arrayNum){

		rowPanel = new JPanel();
		rowPanel.setLayout(new GridLayout(1,hnum));
		rowPanel.setBorder(BorderFactory.createLineBorder(Color.white, 2));
		rowPanel.setPreferredSize(new Dimension(screenWidth/8, screenHeight/8));
		rowArray = new ArrayList<JTextArea>();

		for(int i = 0; i < hnum; i++){

			ta = new JTextArea();
			ta.setEditable(false);
			ta.setLineWrap(true);
			ta.setWrapStyleWord(true);
			ta.setPreferredSize(ta.getPreferredSize());

			//alternates colors for rows
			if(row%2 == 0){
				ta.setBackground(new Color(210,222,239));
			} 
			else{
				ta.setBackground(new Color(234,239,247));
			}
			ta.setBorder(BorderFactory.createLineBorder(Color.white, 2));
			ta.setText(rowData.get(arrayNum));
			ta.setFont(new Font("Arial", Font.PLAIN, 25));
			ta.addMouseListener(new MouseListener(){

				//Mouse Listener for when the user wishes to select an entire row for modfication or deletion
				public void mouseClicked(MouseEvent e) {
					//If the JTextArea clicked is Yellow, change it back to original color
					if (e.getComponent().getBackground() == Color.YELLOW){
						highlight = false; //boolean used to control if a row is already selected
						for (int j = 0; j < dataArray.get(row).size(); j++){
							if(row%2 == 0){
								dataArray.get(row).get(j).setBackground(new Color(210,222,239));
							} 
							else{
								dataArray.get(row).get(j).setBackground(new Color(234,239,247));
							}
						}
					}
					else if (highlight == false){//if no row is selected, select one
						highlight = true;
						setRowIndex(row);
						for (int j = 0; j < dataArray.get(row).size(); j++){
							dataArray.get(row).get(j).setBackground(Color.YELLOW);
						}
					}
					else{
						//Increase size of the buttons
						UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("ARIAL",Font.PLAIN,40))); 
						//Increase size of the textfont
						UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("ARIAL",Font.PLAIN,40)));

						JOptionPane.showMessageDialog(null, "Only one row may be selected at a time", null, JOptionPane.PLAIN_MESSAGE, null);	
					}
				}


				public void mouseEntered(MouseEvent e) {

				}

				public void mouseExited(MouseEvent e) {

				}

				public void mousePressed(MouseEvent e) {

				}

				public void mouseReleased(MouseEvent e) {

				}
			});//End Mouse Listeners
			rowPanel.add(ta);
			rowArray.add(ta);
			arrayNum++;
		}
		dataArray.add(rowArray);

	}//End makeGrid method

	/**
	 * Set the selected row number
	 * @param row - the row number that is selected (yellow)
	 */
	private static void setRowIndex(int row){
		rowIndex = row;
	}//End setRowIndex

	/**
	 * Get the selected row number
	 * @return rowIndex - the row number that is selected (yellow)
	 */
	private static int getRowIndex(){
		return rowIndex;
	}//End getRowIndex

	/**
	 * Obtains the text Strings of the JTextAreas in the row that is highlighted yellow
	 * @return results - ArrayList<String> containing the text in the row of highlighted JTextAreas
	 */
	public static ArrayList<String> getEnteredResults(){

		if(highlight==false){
			//Increase size of the buttons
			UIManager.put("OptionPane.buttonFont", new FontUIResource(new Font("ARIAL",Font.PLAIN,40))); 
			//Increase size of the textfont
			UIManager.put("OptionPane.messageFont", new FontUIResource(new Font("ARIAL",Font.PLAIN,40)));

			JOptionPane.showMessageDialog(null, "Please select a row first", null, JOptionPane.PLAIN_MESSAGE, null);	
			return null;
		}
		ArrayList<String> results = new ArrayList<String>();

		for(int i = 0; i < dataArray.get(rowIndex).size(); i++){
			results.add(dataArray.get(rowIndex).get(i).getText());
		}
		return results;
	}//End getEnteredResults

	/**
	 * Add a new row to the current grid - must combine all rows into one ArrayList<String> and
	 * add the new one to the end if there are no empty spaces
	 * @param a - the ArrayList<String> containing the new row
	 * @param headers - the headers for the columns
	 */
	public static void addNewResult(ArrayList<String> a, ArrayList<String> headers){
		ArrayList<String> b = combineStrings();

		boolean isNull = false;
		//if there is a blank in the current grid
		for(int i = 0; i < b.size(); i = i+headers.size()){
			if (b.get(i).equals("")){
				for(int j = i; j <= (i+(headers.size()-1)); j++){
					b.set(j, a.get(j-i));
				}
				isNull = true;
				break;
			}
		}

		if(isNull == false){
			for(int i = 0; i < a.size(); i++){
				if(a.get(i) == null){ //if ArrayList has null values (if list got expanded too much)
					break;
				}
				b.add(a.get(i));
			}
		}

		refreshGUI(b, headers);

	}//End addNewResult

	/**
	 * Modifies a row that is highlighted yellow, show modifications, and return row to previous color
	 * @param a - an ArrayList<String> of the modified row
	 */
	public static void modifyResult(ArrayList<String> a){

		int r = getRowIndex();

		for(int i = 0; i < a.size(); i++){
			dataArray.get(r).get(i).setText(a.get(i));
			if(r%2 == 0){
				dataArray.get(r).get(i).setBackground(new Color(210,222,239));
			} 
			else{
				dataArray.get(r).get(i).setBackground(new Color(234,239,247));
			}
		}
		highlight = false;
		GUI.centerPanel.revalidate();
		GUI.centerPanel.repaint();

	}//End modifyResult method

	/**
	 * Deletes a row that is highlighted yellow
	 * In order to reduce the panel resizing components, a new row with "" values is added to the end of the
	 * ArrayList<String>
	 * @param headers - ArrayList<String> of the header names for the columns
	 */
	public static void deleteResult(ArrayList<String> headers){

		int r = getRowIndex();

		dataArray.remove(r);
		ArrayList<String> a = combineStrings();
		for(int i = 0; i < headers.size(); i++){
			a.add("");
		}
		highlight = false;
		refreshGUI(a, headers);
	}//End deleteResult Method

	/**
	 * Combines all rows into one ArrayList<String> for addition/removal
	 * @return an ArrayList<String> of all rows
	 */
	private static ArrayList<String> combineStrings(){
		ArrayList<String> contents = new ArrayList<String>();

		for(int i = 0; i < dataArray.size(); i++){
			for(int j = 0; j < dataArray.get(i).size(); j++){
				contents.add(dataArray.get(i).get(j).getText());
			}
		}
		return contents;

	}//End combineStrings method

	/**
	 * Refreshes the GUI to reflect the new grid with changes
	 * @param c - the ArrayList<String> with all rows including new ones
	 * @param head - the ArrayList<String> with all header names for the columns
	 */
	private static void refreshGUI(ArrayList<String> c, ArrayList<String> head){
		GUI.centerPanel.removeAll();
		GUI.centerPanel.add(new Grids(head.size(), head, (c.size())/(head.size()), c)); 
		GUI.centerPanel.revalidate();
		GUI.centerPanel.repaint();
	}//End of refreshGUI method
	
	/**
	 * Allows another class to set the row highlighter back to false in the event a row is highlighted and then main menu is hit
	 * before the row is unhighlighted
	 */
	public static void setHighLight(){
		highlight = false;
	}//End setHighLight method



}//End of Class

